/*****
  ** @file     : stockpile_f103cb.c/h
  ** @brief    : Flash存储库
*****/

//Oneself
#include "stockpile_f303cc.h"

////LL_Driver
//#include "stm32f0xx_ll_flash_ex.h"

////LL库FLASH清除函数
//extern void FLASH_PageErase(uint32_t PageAddress);

/*************************************************************** Flash_Start ***************************************************************/
/*************************************************************** Flash_Start ***************************************************************/
/*************************************************************** Flash_Start ***************************************************************/
//Flash分区表实例
Stockpile_FLASH_Typedef    stockpile_app_firmware    = {STOCKPILE_APP_FIRMWARE_ADDR, STOCKPILE_APP_FIRMWARE_SIZE,    (STOCKPILE_APP_FIRMWARE_SIZE / Stockpile_Page_Size),    0};
Stockpile_FLASH_Typedef    stockpile_quick_cali        = {STOCKPILE_APP_CALI_ADDR,         STOCKPILE_APP_CALI_SIZE,            (STOCKPILE_APP_CALI_SIZE / Stockpile_Page_Size),            0};
Stockpile_FLASH_Typedef stockpile_data                    = {STOCKPILE_APP_DATA_ADDR,            STOCKPILE_APP_DATA_SIZE,             (STOCKPILE_APP_DATA_SIZE / Stockpile_Page_Size),            0};

uint32_t *ptrd;
uint32_t word_num = ((STOCKPILE_APP_CALI_SIZE) >> 2);//计算字数量
/**
  * @brief  Flash数据清空
  * @param  stockpile    Flash分区表实例
  * @retval NULL
**/
void Stockpile_Flash_Data_Empty(Stockpile_FLASH_Typedef *stockpile)
{
    uint32_t count;
    fmc_unlock();    //LL_FLASH_Unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    
    for(count = 0; count < stockpile->page_num; count++)
    {
        fmc_page_erase(stockpile->begin_add + (count * Stockpile_Page_Size));
        fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR);
    }
    fmc_lock();    //LL_FLASH_Lock();
}

//查询FLASH是否擦除干净
void fmc_erase_pages_check(Stockpile_FLASH_Typedef *stockpile)
{
    uint32_t i;

    ptrd = (uint32_t *)stockpile->begin_add;

    /* check flash whether has been erased */
    for(i = 0; i < stockpile->page_num; i++){
        if(0xFFFFFFFF != (*ptrd)){
            break;
        }else{
            ptrd++;
        }
    }
}

/**
  * @brief  Flash数据开始写入
  * @param  stockpile    Flash分区表实例
  * @retval NULL
**/
void Stockpile_Flash_Data_Begin(Stockpile_FLASH_Typedef *stockpile)
{
    fmc_unlock();    //LL_FLASH_Unlock();
    stockpile->asce_write_add = stockpile->begin_add;
}

/**
  * @brief  Flash数据结束写入
  * @param  stockpile    Flash分区表实例
  * @retval NULL
**/
void Stockpile_Flash_Data_End(Stockpile_FLASH_Typedef *stockpile)
{
    fmc_lock();    //LL_FLASH_Lock();
}

/**
  * @brief  Flash设置写地址
  * @param  stockpile    Flash分区表实例
  * @param  write_add    写地址
  * @retval NULL
**/
void Stockpile_Flash_Data_Set_Write_Add(Stockpile_FLASH_Typedef *stockpile, uint32_t write_add)
{
    if(write_add < stockpile->begin_add)                        return;
    if(write_add > stockpile->begin_add + stockpile->area_size)    return;
    stockpile->asce_write_add = write_add;
}

/**
  * @brief  Flash_16位数据写入
  * @param  stockpile    Flash分区表实例
  * @param  data        半字数据缓冲区
  * @param  num            半字数量
  * @retval NULL
**/
void Stockpile_Flash_Data_Write_Data16(Stockpile_FLASH_Typedef *stockpile, uint16_t *data, uint32_t num)
{
    if(stockpile->asce_write_add < stockpile->begin_add)                                    return;
    if((stockpile->asce_write_add + num * 2) > stockpile->begin_add + stockpile->area_size)    return;
    for(uint32_t i=0; i<num; i++)
    {
        if(fmc_halfword_program(stockpile->asce_write_add, data[i]) == FMC_READY)
            stockpile->asce_write_add += 2;
    }
}

/**
  * @brief  Flash_32位数据写入
  * @param  stockpile    Flash分区表实例
  * @param  data        字数据缓冲区
  * @param  num            字数量
  * @retval NULL
**/
void Stockpile_Flash_Data_Write_Data32(Stockpile_FLASH_Typedef *stockpile, uint32_t *data, uint32_t num)
{
    uint16_t *p = (uint16_t*)data;
    Stockpile_Flash_Data_Write_Data16(stockpile, p, num*2);
}

/**
  * @brief  Flash_64位数据写入
  * @param  stockpile    Flash分区表实例
  * @param  data        双字数据缓冲区
  * @param  num            双字数量
  * @retval NULL
**/
void Stockpile_Flash_Data_Write_Data64(Stockpile_FLASH_Typedef *stockpile, uint64_t *data, uint32_t num)
{
    uint16_t *p = (uint16_t*)data;
    Stockpile_Flash_Data_Write_Data16(stockpile, p, num*4);
}
/*************************************************************** Flash_End ***************************************************************/
/*************************************************************** Flash_End ***************************************************************/
/*************************************************************** Flash_End ***************************************************************/

